home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Utilities / Datatypes / acbm / dispatch.c < prev    next >
C/C++ Source or Header  |  1997-05-30  |  35KB  |  1,103 lines

  1.  
  2. /*
  3. **
  4. **  $VER: dispatch.c 1.1 (30.5.97)
  5. **  acbm.datatype 1.1
  6. **
  7. **  Dispatch routine for a DataTypes class
  8. **
  9. **  Written 1996/97 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14. /* main includes */
  15. #include "classbase.h"
  16.  
  17. /* ansi includes */
  18. #include <limits.h>
  19.  
  20. /*****************************************************************************/
  21.  
  22. /* local prototypes */
  23. static                 LONG              LoadACBM( struct ClassBase *, Object * );
  24. static                 BOOL              CMAP2Object( struct ClassBase *, Object *, UBYTE *, ULONG );
  25. static                 LONG              LoadABITBody( struct BitMap *, struct BitMapHeader *, BYTE *, ULONG );
  26.  
  27. static                 ULONG             SaveIFFACBM( struct ClassBase *, Object *, struct dtWrite * );
  28.  
  29. static                 struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
  30.  
  31. static                 LONG              PutIFFObjectInfo( struct ClassBase *, struct IFFHandle *, STRPTR, STRPTR, STRPTR, STRPTR, STRPTR );
  32. static                 LONG              PutIFFString( struct ClassBase *, struct IFFHandle *, ULONG, STRPTR );
  33.  
  34. static                 LONG              PutILBMCMAP( struct ClassBase *, struct IFFHandle *, ULONG *, ULONG );
  35. static                 LONG              PutACBMABIT( struct ClassBase *, struct IFFHandle *, struct BitMap *, struct BitMapHeader * );
  36.  
  37.  
  38.  
  39. /*****************************************************************************/
  40.  
  41. /* Create "acbm.datatype" BOOPSI class */
  42. struct IClass *initClass( struct ClassBase *cb )
  43. {
  44.     struct IClass *cl;
  45.  
  46.     /* Create our class... */
  47.     if( cl = MakeClass( ACBMDTCLASS, PICTUREDTCLASS, NULL, 0UL, 0UL ) )
  48.     {
  49.       cl -> cl_Dispatcher . h_Entry = (HOOKFUNC)Dispatch;
  50.       cl -> cl_UserData             = (ULONG)cb;
  51.  
  52.       AddClass( cl );
  53.     }
  54.  
  55.     return( cl );
  56. }
  57.  
  58. /*****************************************************************************/
  59.  
  60. /* IFF errors to DOS errors */
  61. const
  62. LONG ifferr2doserr[] =
  63. {
  64.     0L,                         /* End of file (not an error).                   */
  65.     0L,                         /* End of context (not an error).                */
  66.     DTERROR_INVALID_DATA,       /* No lexical scope.                             */
  67.     ERROR_NO_FREE_STORE,        /* Insufficient memory.                          */
  68.     ERROR_SEEK_ERROR,           /* Stream read error.                            */
  69.     ERROR_SEEK_ERROR,           /* Stream write error.                           */
  70.     ERROR_SEEK_ERROR,           /* Stream seek error.                            */
  71.     DTERROR_INVALID_DATA,       /* File is corrupt.                              */
  72.     DTERROR_INVALID_DATA,       /* IFF syntax error.                             */
  73.     ERROR_OBJECT_WRONG_TYPE,    /* Not an IFF file.                              */
  74.     ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing.              */
  75.     0xDEADDEAD                  /* Return to client. You should never see this ! */
  76. };
  77.  
  78. /*****************************************************************************/
  79.  
  80.  
  81. struct MyStackSwapStruct
  82. {
  83.     struct StackSwapStruct  stk;
  84.     struct IClass          *cl;
  85.     Object                 *o;
  86.     Msg                     msg;
  87. };
  88.  
  89. /*****************************************************************************/
  90.  
  91. /* Class entry
  92.  * Swaps stack on demand (e.g. too small stack
  93.  */
  94. DISPATCHERFLAGS
  95. ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
  96. {
  97.     struct ClassBase         *cb = (struct ClassBase *)(cl -> cl_UserData);
  98.     ULONG                     retval;
  99.     struct MyStackSwapStruct  mystk;
  100.     UBYTE                    *lower,
  101.                              *upper,
  102.                              *sp;
  103.     struct Task              *ThisTask;
  104.     ULONG                     stacksize;
  105.  
  106.     mystk . cl                = cl;
  107.     mystk . o                 = o;
  108.     mystk . msg               = msg;
  109.  
  110.     ThisTask = FindTask( NULL );
  111.     stacksize = (ULONG)(((UBYTE *)(ThisTask -> tc_SPReg)) - ((UBYTE *)(ThisTask -> tc_SPLower)));
  112.  
  113. #define DTSTACKSIZE (16384UL)
  114.  
  115.     /* Enougth stack ? */
  116.     if( stacksize > (DTSTACKSIZE / 2UL) )
  117.     {
  118.       retval = MyDispatch( (&mystk) );
  119.     }
  120.     else
  121.     {
  122.       /* Alloc a new stack frame... */
  123.       while( !(lower = (UBYTE *)AllocMem( DTSTACKSIZE, (MEMF_PUBLIC | MEMF_CLEAR) )) );
  124.  
  125.       sp = upper = lower + DTSTACKSIZE;
  126.  
  127.       mystk . stk . stk_Lower   = lower;
  128.       mystk . stk . stk_Upper   = (ULONG)upper;
  129.       mystk . stk . stk_Pointer = sp;
  130.  
  131.       retval = SwapMe( (&mystk) );
  132.  
  133.       FreeMem( lower, DTSTACKSIZE );
  134.     }
  135.  
  136.     return( retval );
  137. }
  138.  
  139.  
  140. /* Swap stack and call main dispatcher */
  141. DISPATCHERFLAGS
  142. ULONG SwapMe( REGA0 struct MyStackSwapStruct *mystk )
  143. {
  144.     register ULONG retval;
  145.  
  146. #define cb ((struct ClassBase *)(mystk -> cl -> cl_UserData))
  147.  
  148.     StackSwap( (&(mystk -> stk)) );
  149.  
  150.       retval = MyDispatch( mystk );
  151.  
  152.     StackSwap( (&(mystk -> stk)) );
  153.  
  154. #undef cb
  155.  
  156.     return( retval );
  157. }
  158.  
  159.  
  160. /* main class dispatcher */
  161. DISPATCHERFLAGS
  162. ULONG MyDispatch( REGA0 struct MyStackSwapStruct *mystk )
  163. {
  164.     struct IClass        *cl  = mystk -> cl;
  165.     Object               *o   = mystk -> o;
  166.     Msg                   msg = mystk -> msg;
  167.  
  168.     struct ClassBase     *cb = (struct ClassBase *)(cl -> cl_UserData);
  169.     ULONG                 retval = 0UL;
  170.  
  171.     switch( msg -> MethodID )
  172.     {
  173. /****** acbm.datatype/OM_NEW *************************************************
  174. *
  175. *    NAME
  176. *        OM_NEW -- Create a acbm.datatype object.
  177. *
  178. *    FUNCTION
  179. *        The OM_NEW method is used to create an instance of the acbm.datatype
  180. *        class.  This method is passed to the superclass first. After this,
  181. *        acbm.datatype parses the description file and loads bitmap,
  182. *        colormaps and so on.
  183. *
  184. *    ATTRIBUTES
  185. *        The following attributes can be specified at creation time.
  186. *
  187. *        DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
  188. *            attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
  189. *            If any other type was set in a given DTA_SourceType,
  190. *            OM_NEW will be rejected.
  191. *            Defaults to DTST_FILE.
  192. *
  193. *        DTA_Handle -- For both supported DTST_FILE and DTST_CLIPBOARD, a
  194. *            (struct IFFHandle *) is expected.
  195. *            (DTST_FILE expects a IFF Stream handle because this is a IFF
  196. *            type DataType (DTF_IFF)).
  197. *            A DTST_RAM (create empty object) source type requires a NULL
  198. *            handle.
  199. *
  200. *    BUGS
  201. *
  202. *    RESULT
  203. *        If the object was created a pointer to the object is returned,
  204. *        otherwise NULL is returned.
  205. *
  206. ******************************************************************************
  207. *
  208. */
  209.       case OM_NEW:
  210.       {
  211.           struct TagItem *ti;
  212.  
  213.           /* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
  214.           if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
  215.           {
  216.             if( ((ti -> ti_Data) != DTST_FILE)      &&
  217.                 ((ti -> ti_Data) != DTST_CLIPBOARD) &&
  218.                 ((ti -> ti_Data) != DTST_RAM) )
  219.             {
  220.               SetIoErr( ERROR_OBJECT_WRONG_TYPE );
  221.  
  222.               break;
  223.             }
  224.           }
  225.  
  226.           /* This must not be a subclass of acbm.datatype
  227.            * (not implemented yet)
  228.            */
  229.           if( o == (Object *)cl )
  230.           {
  231.             if( retval = DoSuperMethodA( cl, o, msg ) )
  232.             {
  233.               LONG error;
  234.  
  235.               /* Load picture... */
  236.               if( error = LoadACBM( cb, (Object *)retval ) )
  237.               {
  238.                 /* Something went fatally wrong, dispose object */
  239.                 CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
  240.                 retval = 0UL;
  241.               }
  242.  
  243.               SetIoErr( error );
  244.             }
  245.           }
  246.           else
  247.           {
  248.             /* Subclasses of acbm.datatype are not implemented */
  249.             SetIoErr( ERROR_NOT_IMPLEMENTED );
  250.           }
  251.       }
  252.           break;
  253.  
  254.      case OM_UPDATE:
  255.       {
  256.           if( DoMethod( o, ICM_CHECKLOOP ) )
  257.           {
  258.             break;
  259.           }
  260.       }
  261.       case OM_SET:
  262.       {
  263.           /* Pass the attributes to the picture class and force a refresh if we need it */
  264.           if( retval = DoSuperMethodA( cl, o, msg ) )
  265.           {
  266. /* The following check statement isn't needed because OM_NEW does not allow subclasses of acbm.datatype,
  267.  * therefore, we're always the top instance...
  268.  */
  269. #ifdef COMMENTED_OUT
  270.             /* Top instance ? */
  271.             if( OCLASS( o ) == cl )
  272. #endif /* COMMENTED_OUT */
  273.             {
  274.               struct RastPort *rp;
  275.  
  276.               /* Get a pointer to the rastport */
  277.               if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
  278.               {
  279.                 struct gpRender gpr;
  280.  
  281.                 /* Force a redraw */
  282.                 gpr . MethodID   = GM_RENDER;
  283.                 gpr . gpr_GInfo  = ((struct opSet *)msg) -> ops_GInfo;
  284.                 gpr . gpr_RPort  = rp;
  285.                 gpr . gpr_Redraw = GREDRAW_UPDATE;
  286.  
  287.                 DoMethodA( o, (Msg)(&gpr) );
  288.  
  289.                 /* Release the temporary rastport */
  290.                 ReleaseGIRPort( rp );
  291.  
  292.                 retval = 0UL;
  293.               }
  294.             }
  295.           }
  296.       }
  297.           break;
  298.  
  299. /****** acbm.datatype/DTM_WRITE **********************************************
  300. *
  301. *    NAME
  302. *        DTM_WRITE -- Save data
  303. *
  304. *    FUNCTION
  305. *        This method saves the object's contents to disk.
  306. *
  307. *        If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
  308. *        superclass, picture.datatype, which writes an IFF ILBM picture.
  309. *
  310. *        If dtw_mode is DTWM_RAW, the object saved an IFF ACBM picture to
  311. *        the filehandle given.
  312. *
  313. *    TAGS
  314. *        None defined.
  315. *
  316. *    RESULT
  317. *        Returns 0 for failure (IoErr() returns result2), non-zero
  318. *        for success.
  319. *
  320. ******************************************************************************
  321. *
  322. */
  323.       case DTM_WRITE:
  324.       {
  325.           struct dtWrite *dtw;
  326.  
  327.           dtw = (struct dtWrite *)msg;
  328.  
  329.           /* Local data format requested ? */
  330.           if( (dtw -> dtw_Mode) == DTWM_RAW )
  331.           {
  332.             retval = SaveIFFACBM( cb, o, dtw );
  333.           }
  334.           else
  335.           {
  336.             /* Pass msg to superclass (which writes an IFF ILBM picture)... */
  337.             retval = DoSuperMethodA( cl, o, msg );
  338.           }
  339.       }
  340.           break;
  341.  
  342.       /* Let the superclass handle everything else */
  343.       default:
  344.       {
  345.           retval = DoSuperMethodA( cl, o, msg );
  346.       }
  347.           break;
  348.     }
  349.  
  350.     return( retval );
  351. }
  352.  
  353.  
  354. static
  355. LONG LoadACBM( struct ClassBase *cb, Object *o )
  356. {
  357.     LONG                 error = 0L;
  358.  
  359.  
  360.     APTR                 fh;               /* IFF stream handle               */
  361.     ULONG                sourcetype;       /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
  362.     struct BitMapHeader *bmh;              /* obj's bitmapheader              */
  363.     ULONG                modeid     = 0UL; /* picture's view mode             */
  364.  
  365.     /* Get file handle, handle type and BitMapHeader */
  366.     if( GetDTAttrs( o, DTA_SourceType,    (&sourcetype),
  367.                        DTA_Handle,        (&fh),
  368.                        PDTA_BitMapHeader, (&bmh),
  369.                        TAG_DONE ) == 3UL )
  370.     {
  371.       struct IFFHandle *iff = NULL;
  372.  
  373.       switch( sourcetype )
  374.       {
  375.         case DTST_CLIPBOARD:
  376.         case DTST_FILE:
  377.         {
  378.             /* This is an IFF DataType, datatypesclass provides an IFFHandle for us.
  379.              * (See datatypesclass autdocs for details !)
  380.              */
  381.             iff = (struct IFFHandle *)fh;
  382.         }
  383.             break;
  384.  
  385.         case DTST_RAM:
  386.         {
  387.             /* Do nothing... */
  388.         }
  389.             break;
  390.  
  391.         default:
  392.         {
  393.             /* unsupported source type */
  394.             error = ERROR_NOT_IMPLEMENTED;
  395.         }
  396.             break;
  397.       }
  398.  
  399.       /* Any error ? */
  400.       if( error == 0L )
  401.       {
  402.         /* Any handle to proccess ? */
  403.         if( iff )
  404.         {
  405.           struct BitMap         *bm       = NULL; /* resulting bitmap (e.g. PDTA_BitMap) */
  406.  
  407.           struct StoredProperty *bmhdprop       = NULL, /* ACBM BMHD (struct BitMapHeader) */
  408.                                 *camgprop       = NULL, /* ACBM CAMG (amiga view mode id)  */
  409.                                 *cmapprop       = NULL, /* ACBM CMAP (colormap)            */
  410.                                 *abitprop       = NULL, /* ACBM ABIT (Amiga BITplanes      */
  411.                                 *annoprop       = NULL, /* Generic IFF ANNO (annotation) chunk    */
  412.                                 *authprop       = NULL, /* Generic IFF AUTH (author) chunk        */
  413.                                 *copyrightprop  = NULL, /* Generic IFF (C)  (copyright) chunk     */
  414.                                 *fverprop       = NULL, /* Generic IFF FVER (version) chunk       */
  415.                                 *nameprop       = NULL; /* Generic IFF NAME (name) chunk          */
  416.  
  417. #define NUM_PROPCHUNKS (9L)
  418.           const
  419.           LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
  420.           {
  421.             ID_ACBM, ID_BMHD,
  422.             ID_ACBM, ID_CAMG,
  423.             ID_ACBM, ID_CMAP,
  424.             ID_ACBM, ID_ABIT,
  425.             ID_ACBM, ID_ANNO,
  426.             ID_ACBM, ID_AUTH,
  427.             ID_ACBM, ID_Copyright,
  428.             ID_ACBM, ID_FVER,
  429.             ID_ACBM, ID_NAME
  430.           };
  431.  
  432.           if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
  433.           {
  434.             /* Scan IFF stream until an error or an EOF occurs */
  435.             for( ;; )
  436.             {
  437.               if( error = ParseIFF( iff, IFFPARSE_STEP ) )
  438.               {
  439.                 /* EOF (End Of File) is no error here... */
  440.                 if( error == IFFERR_EOF )
  441.                 {
  442.                   error = 0L;
  443.                   break;
  444.                 }
  445.  
  446.                 /* bmhd header loaded ? */
  447.                 if( bmhdprop == NULL )
  448.                 {
  449.                   if( bmhdprop = FindProp( iff, ID_ACBM, ID_BMHD ) )
  450.                   {
  451.                     *bmh = *((struct BitMapHeader *)(bmhdprop -> sp_Data));
  452.  
  453.                     /* ABIT data __must__ not be compressed for IFF ACBM */
  454.                     if( (bmh -> bmh_Compression) != cmpNone )
  455.                     {
  456.                       error = DTERROR_INVALID_DATA;
  457.                     }
  458.                   }
  459.                 }
  460.  
  461.                 /* camg loaded ? */
  462.                 if( camgprop == NULL )
  463.                 {
  464.                   if( camgprop = FindProp( iff, ID_ACBM, ID_CAMG ) )
  465.                   {
  466.                     modeid = *(ULONG *)(camgprop -> sp_Data);
  467.                   }
  468.                 }
  469.  
  470.                 /* cmap loaded  ? */
  471.                 if( cmapprop == NULL )
  472.                 {
  473.                   if( cmapprop = FindProp( iff, ID_ACBM, ID_CMAP ) )
  474.                   {
  475.                     if( !CMAP2Object( cb, o, (cmapprop -> sp_Data), (cmapprop -> sp_Size) ) )
  476.                     {
  477.                       error = ERROR_NO_FREE_STORE;
  478.                     }
  479.                   }
  480.                 }
  481.  
  482.                 /* annotation loaded ? */
  483.                 if( annoprop == NULL )
  484.                 {
  485.                   /* IFF ANNO found ? */
  486.                   if( annoprop = FindProp( iff, ID_ILBM, ID_ANNO ) )
  487.                   {
  488.                     STRPTR buff;
  489.  
  490.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  491.                     if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
  492.                     {
  493.                       stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
  494.  
  495.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
  496.  
  497.                       FreeVec( buff );
  498.                     }
  499.                     else
  500.                     {
  501.                       /* no temp. buffer */
  502.                       error = ERROR_NO_FREE_STORE;
  503.                     }
  504.                   }
  505.                 }
  506.  
  507.                 /* autor loaded ? */
  508.                 if( authprop == NULL )
  509.                 {
  510.                   /* IFF AUTH found ? */
  511.                   if( authprop = FindProp( iff, ID_ILBM, ID_AUTH ) )
  512.                   {
  513.                     STRPTR buff;
  514.  
  515.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  516.                     if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
  517.                     {
  518.                       stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
  519.  
  520.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
  521.  
  522.                       FreeVec( buff );
  523.                     }
  524.                     else
  525.                     {
  526.                       /* no temp. buffer */
  527.                       error = ERROR_NO_FREE_STORE;
  528.                     }
  529.                   }
  530.                 }
  531.  
  532.                 /* copyright loaded ? */
  533.                 if( copyrightprop == NULL )
  534.                 {
  535.                   /* IFF (C) found ? */
  536.                   if( copyrightprop = FindProp( iff, ID_ILBM, ID_Copyright ) )
  537.                   {
  538.                     STRPTR buff;
  539.  
  540.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  541.                     if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
  542.                     {
  543.                       stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
  544.  
  545.                       SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
  546.  
  547.                       FreeVec( buff );
  548.                     }
  549.                     else
  550.                     {
  551.                       /* no temp. buffer */
  552.                       error = ERROR_NO_FREE_STORE;
  553.                     }
  554.                   }
  555.                 }
  556.  
  557.                 /* file version loaded ? */
  558.                 if( fverprop == NULL )
  559.                 {
  560.                   /* IFF FVER found ? */
  561.                   if( fverprop = FindProp( iff, ID_ILBM, ID_FVER ) )
  562.                   {
  563.                     STRPTR buff;
  564.  
  565.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  566.                     if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
  567.                     {
  568.                       stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
  569.  
  570.                       SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
  571.  
  572.                       FreeVec( buff );
  573.                     }
  574.                     else
  575.                     {
  576.                       /* no temp. buffer */
  577.                       error = ERROR_NO_FREE_STORE;
  578.                     }
  579.                   }
  580.                 }
  581.  
  582.                 /* name loaded ? */
  583.                 if( nameprop == NULL )
  584.                 {
  585.                   /* IFF NAME found ? */
  586.                   if( nameprop = FindProp( iff, ID_ILBM, ID_NAME ) )
  587.                   {
  588.                     STRPTR buff;
  589.  
  590.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  591.                     if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
  592.                     {
  593.                       stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
  594.  
  595.                       SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
  596.  
  597.                       FreeVec( buff );
  598.                     }
  599.                     else
  600.                     {
  601.                       /* no temp. buffer */
  602.                       error = ERROR_NO_FREE_STORE;
  603.                     }
  604.                   }
  605.                 }
  606.  
  607.                 /* abit loaded  ? */
  608.                 if( abitprop == NULL )
  609.                 {
  610.                   if( abitprop = FindProp( iff, ID_ACBM, ID_ABIT ) )
  611.                   {
  612.                     if( bmhdprop )
  613.                     {
  614.                       if( bm = AllocBitMap( (ULONG)(bmh -> bmh_Width), (ULONG)(bmh -> bmh_Height), (ULONG)(bmh -> bmh_Depth), 0UL, NULL ) )
  615.                       {
  616.                         error = LoadABITBody( bm, bmh, (abitprop -> sp_Data), (abitprop -> sp_Size) );
  617.                       }
  618.                       else
  619.                       {
  620.                         /* Not bitmap (AllocBitMap failed) */
  621.                         error = ERROR_NO_FREE_STORE;
  622.                       }
  623.                     }
  624.                     else
  625.                     {
  626.                       /* No BMHD chunk before ABIT chunk */
  627.                       error = DTERROR_INVALID_DATA;
  628.                     }
  629.                   }
  630.                 }
  631.  
  632.                 /* on error: leave for-loop */
  633.                 if( error )
  634.                 {
  635.                   if( error != IFFERR_EOC )
  636.                   {
  637.                     break;
  638.                   }
  639.                 }
  640.               }
  641.             }
  642.           }
  643.  
  644.           /* bmh, cmap, abit and all other required information available  ? */
  645.           if( ((bmhdprop == NULL) || (cmapprop == NULL) || (abitprop == NULL) || (bm == NULL)) && (error == 0L) )
  646.           {
  647.             error = DTERROR_INVALID_DATA;
  648.           }
  649.  
  650.           /* Any error ? */
  651.           if( error == 0L )
  652.           {
  653.             /* No name chunk ? */
  654.             if( nameprop == NULL )
  655.             {
  656.               STRPTR name;
  657.  
  658.               GetDTAttrs( o, DTA_Name, (&name), TAG_DONE );
  659.               SetDTAttrs( o, NULL, NULL, DTA_ObjName, name, TAG_DONE );
  660.             }
  661.  
  662.             /* No mode id ? */
  663.             if( modeid == 0UL )
  664.             {
  665.               /* Get best modeid for this dimensions */
  666.               modeid = BestModeID( BIDTAG_NominalWidth,    (bmh -> bmh_PageWidth),
  667.                                    BIDTAG_NominalHeight,   (bmh -> bmh_PageHeight),
  668.                                    BIDTAG_DesiredWidth,    (bmh -> bmh_Width),
  669.                                    BIDTAG_DesiredHeight,   (bmh -> bmh_Height),
  670.                                    BIDTAG_Depth,           (bmh -> bmh_Depth),
  671.                                    BIDTAG_DIPFMustNotHave, (DIPF_IS_DUALPF | DIPF_IS_PF2PRI),
  672.                                    TAG_DONE );
  673.  
  674.               if( modeid == INVALID_ID ) modeid = 0UL;
  675.             }
  676.  
  677.             /* Set misc attributes */
  678.             SetDTAttrs( o, NULL, NULL,
  679.                         PDTA_ModeID,      modeid,
  680.                         PDTA_BitMap,      bm,
  681.                         DTA_NominalHoriz, (bmh -> bmh_Width),
  682.                         DTA_NominalVert,  (bmh -> bmh_Height),
  683.                         TAG_DONE );
  684.           }
  685.         }
  686.         else
  687.         {
  688.           /* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
  689.           if( sourcetype != DTST_RAM )
  690.           {
  691.             /* No handle ! */
  692.             error = ERROR_REQUIRED_ARG_MISSING;
  693.           }
  694.         }
  695.       }
  696.     }
  697.     else
  698.     {
  699.       /* can't get required attributes from superclass */
  700.       error = ERROR_OBJECT_WRONG_TYPE;
  701.     }
  702.  
  703.     /* Error codes below 0 are related to the IFFParse.library functions */
  704.     if( error < 0L )
  705.     {
  706.       /* convert IFFParse error to DOS error */
  707.       error = ifferr2doserr[ (-error - 1) ];
  708.     }
  709.  
  710.     return( error );
  711. }
  712.  
  713.  
  714. /* Put CMAP chunk into picture/animation object... */
  715. static
  716. BOOL CMAP2Object( struct ClassBase *cb, Object *o, UBYTE *rgb, ULONG rgbsize )
  717. {
  718.     struct ColorRegister *acm;
  719.     ULONG                *acregs;
  720.     ULONG                 nc;
  721.  
  722.     /* file has this many colors (e.g. each color has one byte per R,B,G-gun) */
  723.     nc = rgbsize / 3UL;
  724.  
  725.     SetDTAttrs( o, NULL, NULL, PDTA_NumColors, nc, TAG_DONE );
  726.  
  727.     /* Get color context */
  728.     if( GetDTAttrs( o,
  729.                     PDTA_ColorRegisters, (&acm),
  730.                     PDTA_CRegs,          (&acregs),
  731.                     PDTA_NumColors,      (&nc),
  732.                     TAG_DONE ) == 3UL )
  733.     {
  734.       /* All valid ? */
  735.       if( acm && acregs && nc )
  736.       {
  737.         ULONG i;
  738.  
  739.         for( i = 0UL ; i < nc ; i++, acm++ )
  740.         {
  741.           acm -> red   =  *rgb++;
  742.           acm -> green =  *rgb++;
  743.           acm -> blue  =  *rgb++;
  744.  
  745.           /* Replicate the color information.
  746.            * This surrounds an OS bug which uses the low-order bytes of the 32-bit colors
  747.            * instead of the high order ones
  748.            */
  749.           acregs[ ((i * 3) + 0) ] = ((ULONG)(acm -> red))   * 0x01010101UL;
  750.           acregs[ ((i * 3) + 1) ] = ((ULONG)(acm -> green)) * 0x01010101UL;
  751.           acregs[ ((i * 3) + 2) ] = ((ULONG)(acm -> blue))  * 0x01010101UL;
  752.         }
  753.  
  754.         return( TRUE );
  755.       }
  756.     }
  757.  
  758.     return( FALSE );
  759. }
  760.  
  761.  
  762. /* LOad IFF ACBM ABIT chunk into given bitmap */
  763. static
  764. LONG LoadABITBody( struct BitMap *bitmap, struct BitMapHeader *bmhd, BYTE *buffer, ULONG buffersize )
  765. {
  766.     UBYTE    srcPlaneCnt  = bmhd -> bmh_Depth;          /* Haven't counted for mask plane yet */
  767.     WORD     srcRowBytes  = RowBytes( (bmhd -> bmh_Width) );
  768.     WORD     destRowBytes = bitmap -> BytesPerRow;      /* used as a modulo only */
  769.     LONG     nRows        = bmhd -> bmh_Height;
  770.     LONG     iPlane,
  771.              iRow;
  772.     BYTE    *buf;
  773.     BYTE    *planes[ MaxSrcPlanes ];                    /* array of ptrs to planes & mask */
  774.  
  775.     if( nRows > (bitmap -> Rows) )
  776.       nRows = bitmap -> Rows;
  777.  
  778.     /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
  779.     for( iPlane = 0 ; iPlane < (bitmap -> Depth) ; iPlane++ )
  780.     {
  781.       planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
  782.     }
  783.  
  784.     for( ; iPlane < MaxSrcPlanes ; iPlane++ )
  785.     {
  786.       planes[ iPlane ] = NULL;
  787.     }
  788.  
  789.     /* Copy any mask plane ptr into corresponding "planes" slot. */
  790.     if( (bmhd -> bmh_Masking) == mskHasMask )
  791.     {
  792.       planes[ srcPlaneCnt ] = NULL; /* In case more dstPlanes than src. */
  793.       srcPlaneCnt += 1;             /* Include mask plane in count.     */
  794.     }
  795.  
  796.     /* Read the ABIT contents into client's bitmap. */
  797.     buf = buffer;
  798.  
  799.     for( iPlane = 0 ; iPlane < srcPlaneCnt ; iPlane++ )
  800.     {
  801.       for( iRow = nRows ; iRow > 0 ; iRow-- )
  802.       {
  803.         memcpy( planes[ iPlane ], buf, (size_t)srcRowBytes );
  804.         buf += srcRowBytes;
  805.  
  806.         planes[ iPlane ] += destRowBytes; /* Possibly skipping unused bytes */
  807.       }
  808.     }
  809.  
  810.     return( 0L );
  811. }
  812.  
  813.  
  814. /* The IFF ACBM encoder */
  815. static
  816. ULONG SaveIFFACBM( struct ClassBase *cb, Object *o, struct dtWrite *dtw )
  817. {
  818.     ULONG retval = 0UL;
  819.     LONG  error  = 0L;
  820.  
  821.     /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
  822.     if( dtw -> dtw_FileHandle )
  823.     {
  824.       STRPTR               objname,
  825.                            objauthor,
  826.                            objannotation,
  827.                            objcopyright,
  828.                            objversion;
  829.       struct BitMapHeader *bmh;
  830.       ULONG                modeid;
  831.       ULONG               *cregs;
  832.       ULONG                numcolors;
  833.       struct BitMap       *bm;
  834.  
  835.       if( GetDTAttrs( o, DTA_ObjName,       (&objname),
  836.                          DTA_ObjAuthor,     (&objauthor),
  837.                          DTA_ObjAnnotation, (&objannotation),
  838.                          DTA_ObjCopyright,  (&objcopyright),
  839.                          DTA_ObjVersion,    (&objversion),
  840.                          PDTA_BitMapHeader, (&bmh),
  841.                          PDTA_ModeID,       (&modeid),
  842.                          PDTA_CRegs,        (&cregs),
  843.                          PDTA_NumColors,    (&numcolors),
  844.                          PDTA_BitMap,       (&bm),
  845.                          TAG_DONE ) == 10UL )
  846.       {
  847.         if( bmh && cregs && numcolors && bm )
  848.         {
  849.           /* ABIT data __must__ not be compressed for IFF ACBM */
  850.           if( (bmh -> bmh_Compression) == cmpNone )
  851.           {
  852.             /* Check if this is a standard amiga bitmap (we're accessing it directly below, and cannot
  853.              * handle any other bitmap layout than the standart planar format)
  854.              */
  855.             if( GetBitMapAttr( bm, BMA_FLAGS ) & BMF_STANDARD )
  856.             {
  857.               struct IFFHandle *iff;
  858.  
  859.               /* Create IFF handle based in the given file handle */
  860.               if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
  861.               {
  862.                 if( !(error = OpenIFF( iff, IFFF_WRITE )) )
  863.                 {
  864.                   for( ;; ) /* not a loop, used as a jump table */
  865.                   {
  866.                     if( error = PushChunk( iff, ID_ACBM, ID_FORM, IFFSIZE_UNKNOWN ) )
  867.                       break;
  868.  
  869.                     /* write BMHD (BitMapHeader) */
  870.                     {
  871.                       if( error = PushChunk( iff, 0UL, ID_BMHD, IFFSIZE_UNKNOWN ) )
  872.                         break;
  873.  
  874.                       if( WriteChunkBytes( iff, (APTR)bmh, sizeof( struct BitMapHeader ) ) != sizeof( struct BitMapHeader ) )
  875.                       {
  876.                         error = IFFERR_WRITE;
  877.                         break;
  878.                       }
  879.  
  880.                       if( error = PopChunk( iff ) )
  881.                         break;
  882.                     }
  883.  
  884.                     /* write CMAP (global color map) */
  885.                     if( error = PutILBMCMAP( cb, iff, cregs, numcolors ) )
  886.                       break;
  887.  
  888.                     /* write misc info (name, author, annotation etc.) */
  889.                     if( error = PutIFFObjectInfo( cb, iff, objname, objauthor, objannotation, objcopyright, objversion ) )
  890.                       break;
  891.  
  892.                     /* write CAMG (amiga view mode) (if available) */
  893.                     if( (modeid != 0UL) && (modeid != INVALID_ID) )
  894.                     {
  895.                       if( error = PushChunk( iff, 0UL, ID_CAMG, IFFSIZE_UNKNOWN ) )
  896.                         break;
  897.  
  898.                       if( WriteChunkBytes( iff, (APTR)(&modeid), sizeof( ULONG ) ) != sizeof( ULONG ) )
  899.                       {
  900.                         error = IFFERR_WRITE;
  901.                         break;
  902.                       }
  903.  
  904.                       if( error = PopChunk( iff ) )
  905.                         break;
  906.                     }
  907.  
  908.                     /* Write ACBM ABIT */
  909.                     if( error = PutACBMABIT( cb, iff, bm, bmh ) )
  910.                       break;
  911.  
  912.                     if( error = PopChunk( iff ) )
  913.                       break;
  914.  
  915.                     break; /* end of jump table */
  916.                   }
  917.  
  918.                   CloseIFF( iff );
  919.                 }
  920.  
  921.                 /* No error == success */
  922.                 if( error == 0L )
  923.                 {
  924.                   retval = 1UL; /* success ! */
  925.                 }
  926.  
  927.                 FreeIFF( iff );
  928.               }
  929.               else
  930.               {
  931.                 /* Can't alloc iff handle */
  932.                 error = ERROR_NO_FREE_STORE;
  933.               }
  934.             }
  935.             else
  936.             {
  937.               /* unknown bitmap layout (e.g. not a standard amiga bitmap) */
  938.               error = ERROR_OBJECT_WRONG_TYPE;
  939.             }
  940.           }
  941.           else
  942.           {
  943.             /* IFF ACBM does not support compression */
  944.             error = DTERROR_UNKNOWN_COMPRESSION;
  945.           }
  946.         }
  947.         else
  948.         {
  949.           /* Some things are missing (e.g. no bitmap etc.)... */
  950.           error = DTERROR_NOT_ENOUGH_DATA;
  951.         }
  952.       }
  953.       else
  954.       {
  955.         /* Object does not support the attributes we need... */
  956.         error = ERROR_OBJECT_WRONG_TYPE;
  957.       }
  958.     }
  959.  
  960.     /* Error codes below 0 are related to the IFFParse.library functions */
  961.     if( error < 0L )
  962.     {
  963.       /* convert IFFParse error to DOS error */
  964.       error = ifferr2doserr[ (-error - 1) ];
  965.     }
  966.  
  967.     SetIoErr( error );
  968.  
  969.     return( retval );
  970. }
  971.  
  972.  
  973. /* Create IFF handle based on given file handle */
  974. static
  975. struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
  976. {
  977.     struct IFFHandle *iff;
  978.  
  979.     if( iff = AllocIFF() )
  980.     {
  981.       iff -> iff_Stream = (ULONG)fh;
  982.  
  983.       InitIFFasDOS( iff );
  984.     }
  985.  
  986.     return( iff );
  987. }
  988.  
  989.  
  990. /* Put IFF generic info chunks (NAME, AUTH, ANNO, (C), FVER etc. */
  991. static
  992. LONG PutIFFObjectInfo( struct ClassBase *cb, struct IFFHandle *iff, STRPTR objname, STRPTR objauthor, STRPTR objannotation, STRPTR objcopyright, STRPTR objversion )
  993. {
  994.     LONG error;
  995.  
  996.     if( error = PutIFFString( cb, iff, ID_NAME,      objname       ) ) return( error );
  997.     if( error = PutIFFString( cb, iff, ID_AUTH,      objauthor     ) ) return( error );
  998.     if( error = PutIFFString( cb, iff, ID_ANNO,      objannotation ) ) return( error );
  999.     if( error = PutIFFString( cb, iff, ID_Copyright, objcopyright  ) ) return( error );
  1000.     if( error = PutIFFString( cb, iff, ID_FVER,      objversion    ) ) return( error );
  1001.  
  1002.     return( 0L );
  1003. }
  1004.  
  1005.  
  1006. /* write an string into a chunk (like generic AUTH, ANNO etc. chunks)  */
  1007. static
  1008. LONG PutIFFString( struct ClassBase *cb, struct IFFHandle *iff, ULONG id, STRPTR string )
  1009. {
  1010.     LONG error = 0L;
  1011.  
  1012.     if( string )
  1013.     {
  1014.       ULONG len = (ULONG)(strlen( string ) + 1UL);
  1015.  
  1016.       if( error = PushChunk( iff, 0UL, id, IFFSIZE_UNKNOWN ) )
  1017.         return( error );
  1018.  
  1019.       if( WriteChunkBytes( iff, (APTR)string, len ) != len )
  1020.       {
  1021.         return( IFFERR_WRITE );
  1022.       }
  1023.  
  1024.       error = PopChunk( iff );
  1025.     }
  1026.  
  1027.     return( error );
  1028. }
  1029.  
  1030.  
  1031. /* write ILBM CMAP  */
  1032. static
  1033. LONG PutILBMCMAP( struct ClassBase *cb, struct IFFHandle *iff, ULONG *cregs, ULONG numcolors )
  1034. {
  1035.     long                 error;
  1036.     ULONG                i;
  1037.     struct ColorRegister cm;
  1038.  
  1039.     if( error = PushChunk( iff, 0UL, ID_CMAP, IFFSIZE_UNKNOWN ) )
  1040.       return( error );
  1041.  
  1042.     for( i = 0UL ; i < numcolors ; i++ )
  1043.     {
  1044.       /* reduce colors from 32 bits to cmap's 8 bit-per-gun */
  1045.       cm . red   = (UBYTE)(cregs[ ((i * 3) + 0) ] >> 24UL);
  1046.       cm . green = (UBYTE)(cregs[ ((i * 3) + 1) ] >> 24UL);
  1047.       cm . blue  = (UBYTE)(cregs[ ((i * 3) + 2) ] >> 24UL);
  1048.  
  1049.       /* Write R, B, G bytes */
  1050.       if( WriteChunkBytes( iff, (APTR)(&cm), 3UL ) != 3UL )
  1051.       {
  1052.         return( IFFERR_WRITE );
  1053.       }
  1054.     }
  1055.  
  1056.     return( PopChunk( iff ) );
  1057. }
  1058.  
  1059. /*****************************************************************************/
  1060.  
  1061. /* Write ACBM ABIT data */
  1062. static
  1063. LONG PutACBMABIT( struct ClassBase *cb, struct IFFHandle *iff, struct BitMap *bitmap, struct BitMapHeader *bmh )
  1064. {
  1065.     LONG     error;
  1066.     LONG     rowBytes        = bitmap -> BytesPerRow;           /* for source modulo only  */
  1067.     LONG     FileRowBytes    = RowBytes( (bmh -> bmh_Width) );  /* width to write in bytes */
  1068.     ULONG    planeCnt        = bmh -> bmh_Depth;                /* number of bit planes including mask */
  1069.     ULONG    iPlane,
  1070.              iRow;
  1071.     BYTE    *planes[ 24 ]; /* array of ptrs to planes & mask */
  1072.  
  1073.     /* Copy the ptrs to bit & mask planes into local array "planes" */
  1074.     for( iPlane = 0 ; iPlane < planeCnt; iPlane++ )
  1075.        planes[ iPlane ] = (BYTE *)(bitmap -> Planes[ iPlane ]);
  1076.  
  1077.     /* Write out a ABIT chunk header */
  1078.     if( error = PushChunk( iff, 0L, ID_ABIT, IFFSIZE_UNKNOWN ) )
  1079.       return( error );
  1080.  
  1081.     /* Write out the ABIT contents */
  1082.     for( iPlane = 0 ; iPlane < planeCnt ; iPlane++ )
  1083.     {
  1084.       for( iRow = bmh -> bmh_Height ; iRow > 0 ; iRow-- )
  1085.       {
  1086.         /* Write next row.*/
  1087.         if( WriteChunkBytes( iff, planes[ iPlane ], FileRowBytes ) != FileRowBytes )
  1088.           return( IFFERR_WRITE );
  1089.  
  1090.         planes[ iPlane ] += rowBytes; /* Possibly skipping unused bytes */
  1091.       }
  1092.     }
  1093.  
  1094.     /* Finish the chunk */
  1095.     error = PopChunk( iff );
  1096.  
  1097.     return( error );
  1098. }
  1099.  
  1100.  
  1101.  
  1102.  
  1103.